package com.atguigu.spzx.service.pay.service.impl;

import com.alibaba.fastjson.JSON;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeWapPayModel;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.internal.util.StringUtils;
import com.alipay.api.request.AlipayTradeWapPayRequest;
import com.atguigu.spzx.common.handler.exception.SpzxException;
import com.atguigu.spzx.model.common.Result;
import com.atguigu.spzx.model.common.ResultCodeEnum;
import com.atguigu.spzx.model.entity.h5.OrderInfo;
import com.atguigu.spzx.model.entity.h5.PaymentInfo;
import com.atguigu.spzx.service.order.client.feign.OrderClient;
import com.atguigu.spzx.service.pay.config.AlipayConfig;
import com.atguigu.spzx.service.pay.service.PayService;
import com.atguigu.spzx.service.pay.service.PaymentInfoService;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.Map;

/**
 * title:
 * author: zgl
 * date: 2024/1/21
 * description：
 */
@Service
public class PayServiceImpl implements PayService {
    @Resource
    private OrderClient orderClient;

    @Resource
    private PaymentInfoService paymentInfoService;

    @Override
    public String submitAlipay(String orderNo) {
        Result<OrderInfo> result = orderClient.getOrderInfo(orderNo);
        if (result.getCode() != 200) {
            throw new SpzxException(ResultCodeEnum.FAIL);
        }
        OrderInfo orderInfo = result.getData();
        // 商户订单号，商户网站订单系统中唯一订单号，必填
        String out_trade_no = orderNo;
        // 订单名称，必填
        String subject = "尚品甄选商品";
        // 付款金额，必填
        String total_amount = orderInfo.getTotalAmount().toString();
        // 销售产品码 必填
        String product_code = "QUICK_WAP_WAY";
        /**********************/
        // SDK 公共请求类，包含公共请求参数，以及封装了签名与验签，开发者无需关注签名与验签
        //调用RSA签名方式
        AlipayClient client = new DefaultAlipayClient(AlipayConfig.URL, AlipayConfig.APPID,
                AlipayConfig.RSA_PRIVATE_KEY, AlipayConfig.FORMAT, AlipayConfig.CHARSET,
                AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.SIGNTYPE);
        AlipayTradeWapPayRequest alipay_request = new AlipayTradeWapPayRequest();

        // 封装请求支付信息
        AlipayTradeWapPayModel model = new AlipayTradeWapPayModel();
        model.setOutTradeNo(out_trade_no);
        model.setSubject(subject);
        model.setTotalAmount(total_amount);
        model.setBody(null);
//        model.setTimeoutExpress(timeout_express);
        model.setProductCode(product_code);
        alipay_request.setBizModel(model);
        // 设置异步通知地址
        alipay_request.setNotifyUrl(AlipayConfig.notify_url);
        // 设置同步地址
        alipay_request.setReturnUrl(AlipayConfig.return_url);

        try {
            PaymentInfo paymentInfo = new PaymentInfo();
            paymentInfo.setPaymentStatus("0");
            paymentInfo.setPayType(2);
            paymentInfo.setOrderNo(orderNo);
            paymentInfo.setUserId(orderInfo.getUserId());
            paymentInfo.setContent(subject);
            paymentInfo.setAmount(orderInfo.getTotalAmount());
            /*paymentInfo.setOutTradeNo();
          paymentInfo.setCallbackTime();
           paymentInfo.setCallbackContent();*/
            paymentInfoService.savePayInfo(paymentInfo);

            // 调用SDK生成表单
            return client.pageExecute(alipay_request).getBody();
        } catch (AlipayApiException e) {
            // TODO Auto-generated catch block
//            e.printStackTrace();
            throw new SpzxException(ResultCodeEnum.PAY_PAGE_ERROR);
        }
    }


    @Override
    public String payNotify(Map<String, String> params) {
        String tradeNo = params.get("out_trade_no");
        PaymentInfo payInfo = paymentInfoService.getOne(Wrappers.lambdaQuery(PaymentInfo.class).eq(PaymentInfo::getOrderNo, tradeNo));
        try {
            //验签
            boolean flag = AlipaySignature.rsaCheckV1(params, AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.CHARSET, AlipayConfig.SIGNTYPE);
            if (!flag) {
                if (payInfo != null) {
                    payInfo.setCallbackTime(new Date());
                    payInfo.setCallbackContent(JSON.toJSONString(params));
                    payInfo.setPaymentStatus("-1");//私钥公钥验证不通过
                    payInfo.setOutTradeNo(params.get("trade_no"));//支付宝交易单号
                    paymentInfoService.updateById(payInfo);
                }
                throw new SpzxException(ResultCodeEnum.FAIL, null);
            }
            //支付宝交易状态校验
            String tradeStatus = params.get("trade_status");
            if (StringUtils.isEmpty(tradeStatus) || !tradeStatus.equals("TRADE_SUCCESS")) {
                if (payInfo != null) {
                    payInfo.setCallbackTime(new Date());
                    payInfo.setCallbackContent(JSON.toJSONString(params));
                    payInfo.setPaymentStatus("-2");//交易失败
                    payInfo.setOutTradeNo(params.get("trade_no"));//支付宝交易单号
                    paymentInfoService.updateById(payInfo);
                }
                return "success";
            }
            //非法请求
            if (payInfo == null) {
                throw new SpzxException(ResultCodeEnum.FAIL, null);
            }
            //幂等性(已经处理)
            if (!payInfo.getPaymentStatus().equals("0")) {
                return "success";
            }
            //金额校验
            String payAmount = params.get("buyer_pay_amount");
            BigDecimal bigDecimal = new BigDecimal(payAmount);
//            if (payInfo.getAmount().compareTo(bigDecimal) != 0)
            if(payInfo.getAmount().doubleValue()!=bigDecimal.doubleValue()){
                if (payInfo != null) {
                    payInfo.setCallbackTime(new Date());
                    payInfo.setCallbackContent(JSON.toJSONString(params));
                    payInfo.setPaymentStatus("-3");//支付金额不一致
                    payInfo.setOutTradeNo(params.get("trade_no"));//支付宝交易单号
                    paymentInfoService.updateById(payInfo);
                }
                throw new SpzxException(ResultCodeEnum.FAIL, null);
            }
            orderClient.updateOrderStatusPayed(payInfo.getOrderNo(),1);

            payInfo.setCallbackTime(new Date());
            payInfo.setCallbackContent(JSON.toJSONString(params));
            payInfo.setPaymentStatus("1");//支付成功
            payInfo.setOutTradeNo(params.get("trade_no"));//获取支付宝的交易流水号
            paymentInfoService.updateById(payInfo);
            return "success";
            //更新库存和销量
        } catch (Exception e) {
            e.printStackTrace();
            return "fail";
        }
    }
}
